package com.bana.fvs.service;

import com.bana.fvs.protocol.SetControllerTimer;
import com.bana.fvs.utils.FogAreaServer;
import com.bana.sys.code.SendResult;
import com.bana.sys.model.Department;
import com.bana.sys.service.UserService;
import com.bana.sys.socket.SocketResult;
import com.bana.fvs.protocol.CollectSocket;
import com.bana.fvs.task.SocketTask;
import com.bana.fvs.code.*;
import com.bana.fvs.dao.*;
import com.bana.fvs.model.*;

import com.bana.sys.utils.ActionResult;
import com.bana.sys.model.User;
import com.bana.sys.service.CodeService;
import com.bana.sys.service.LogService;
import com.bana.sys.utils.Token;
import com.bana.sys.utils.Tuple;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 雾区
 */
@Service
public class FogAreaService {

    @Resource
    private FogAreaDAO fogAreaDAO;
    @Resource
    private ControllerDAO controllerDAO;
    @Resource
    private VisibilityDAO visibilityDAO;
    @Resource
    private LinkDeviceDAO linkDeviceDAO;
    @Resource
    private ProgramDAO programDAO;
    @Resource
    private HolidayDAO holidayDAO;
    @Resource
    private VisibilityStatisticsDAO visibilityStatisticsDAO;
    @Resource
    private StrategyDAO strategyDAO;
    @Resource
    private WeatherStatisticsDAO weatherStatisticsDAO;
    @Resource
    private CodeService codeService;
    @Resource
    private LinkDeviceService linkDeviceService;
    @Resource
    private LogService logService;
    @Resource
    private UserService userService;
    @Resource
    private ControllerService controllerService;
    @Resource
    private VisibilityService visibilityService;
    @Resource
    private VisibilityScaleService visibilityScaleService;

    /**
     * 上一次发送成功的控制器缓存，键为控制器编码
     */
    private static Map<Integer, Controller> ControllerConfigMap = new ConcurrentHashMap<>();

    /**
     * 雾区缓存，键为雾区编码
     */
    public static Map<Integer, FogArea> FogAreaMap = new ConcurrentHashMap<>();

    /**
     * 能见度统计缓存，键为能见度检测仪标识码,值为雾区能见度队列
     */
    private static Map<String, Queue<VisibilityStatistics>> StatisticsMap = new ConcurrentHashMap<>();

    /**
     * 从数据库查询雾区集合，会根据当前用户权限筛选雾区
     *
     * @return 雾区集合
     * @throws IOException
     */
    public List<FogArea> getFogAreas(String token) {

        User user = Token.getUser(token);
        if (user == null) {
            return new ArrayList<>();
        } else {
            //获取用户的部门树
            userService.fillDepartment(user);
            return fogAreaDAO.getFogAreas(user.getDepartmentPath());
        }
    }

    /**
     * 从数据库和缓存中获取雾区集合
     *
     * @return 雾区集合
     * @throws IOException
     */
    public List<FogArea> queryFogAreas(String token) {

        List<FogArea> fogAreas = getFogAreas(token);
        for (FogArea fogArea : fogAreas) {
            FogArea fogAreaCache = FogAreaMap.get(fogArea.getWqbm());
            if (fogAreaCache != null) {
                //检测仪状态
                fogArea.setJcybsm(fogAreaCache.getJcybsm());
                fogArea.setJcybh(fogAreaCache.getJcybh());
                fogArea.setJcydk(fogAreaCache.getJcydk());
                fogArea.setJcysbzt(fogAreaCache.getJcysbzt());
                fogArea.setJcysbztsm(fogAreaCache.getJcysbztsm());

                //能见度等级
                fogArea.setNjddj(fogAreaCache.getNjddj());
                fogArea.setNjdsx(fogAreaCache.getNjdsx());
                fogArea.setNjdxx(fogAreaCache.getNjdxx());
                fogArea.setNjddjms(fogAreaCache.getNjddjms());

                //能见度
                fogArea.setNjd(fogAreaCache.getNjd());
                fogArea.setNjdyfz(fogAreaCache.getNjdyfz());
                fogArea.setNjdsfz(fogAreaCache.getNjdsfz());

                //天气代码
                fogArea.setTqdm(fogAreaCache.getTqdm());
                fogArea.setTqdmsm(fogAreaCache.getTqdmsm());

                //天气
                fogArea.setWd(fogAreaCache.getWd());
                fogArea.setSd(fogAreaCache.getSd());
                fogArea.setFx(fogAreaCache.getFx());
                fogArea.setFs(fogAreaCache.getFs());
                fogArea.setQy(fogAreaCache.getQy());
                fogArea.setYl(fogAreaCache.getYl());

                //路面
                fogArea.setDmwd(fogAreaCache.getDmwd());
                fogArea.setSmhd(fogAreaCache.getSmhd());
                fogArea.setBhd(fogAreaCache.getBhd());
                fogArea.setXhd(fogAreaCache.getXhd());
                fogArea.setShxs(fogAreaCache.getShxs());
                fogArea.setLmzt(fogAreaCache.getLmzt());

                //继电器
                fogArea.setJdqgzms(fogAreaCache.getJdqgzms());
                fogArea.setJdqgzmssm(fogAreaCache.getJdqgzmssm());

                //方案信息
                fogArea.setGzms(fogAreaCache.getGzms());
                fogArea.setGzmssm(fogAreaCache.getGzmssm());
                fogArea.setFamc(fogAreaCache.getFamc());
                fogArea.setFact(fogAreaCache.isFact());
                fogArea.setKssj(fogAreaCache.getKssj());
                fogArea.setCxsj(fogAreaCache.getCxsj());
                fogArea.setKzcl(fogAreaCache.getKzcl());
                fogArea.setKzclsm(fogAreaCache.getKzclsm());
                fogArea.setSspl(fogAreaCache.getSspl());
                fogArea.setSsplsm(fogAreaCache.getSsplsm());
                fogArea.setZkb(fogAreaCache.getZkb());
                fogArea.setZkbsm(fogAreaCache.getZkbsm());
                fogArea.setWdkz(fogAreaCache.getWdkz());
                fogArea.setWdkzsm(fogAreaCache.getWdkzsm());
                fogArea.setWdlddj(fogAreaCache.getWdlddj());
                fogArea.setWdlddjsm(fogAreaCache.getWdlddjsm());
                fogArea.setWdld(fogAreaCache.getWdld());
                fogArea.setLdsc(fogAreaCache.getLdsc());
                fogArea.setMdsc(fogAreaCache.getMdsc());
                fogArea.setHdys(fogAreaCache.getHdys());
                fogArea.setMqys(fogAreaCache.getMqys());
                fogArea.setHsjsdzsl(fogAreaCache.getHsjsdzsl());

                //光感
                fogArea.setControllers(fogAreaCache.getControllers());

                //控制器状态
                fogArea.setControllers_zt(fogAreaCache.getControllers_zt());

                fogArea.setGxsj(fogAreaCache.getGxsj());
            }
        }
        return fogAreas;

    }

    /**
     * 查询雾区中设备集合
     * 会查询各个设备的缓存，所以可以获取到设备状态
     *
     * @param wqbm 雾区编码
     * @return 设备集合 检测仪，控制器，联动设备
     * @throws IOException
     */
    public List<Object> queryDevices(int wqbm) {
        List<Object> list = new ArrayList<>();
        List<Visibility> visibilities = visibilityService.queryVisibilities(wqbm);
        List<com.bana.fvs.model.Controller> controllers = controllerService.queryControllers(wqbm);
        List<LinkDevice> linkDevices = linkDeviceDAO.getLinkDevices(wqbm, DeviceType.All);
        list.addAll(visibilities);
        list.addAll(controllers);
        list.addAll(linkDevices);
        return list;
    }

    /**
     * 获取设备连接状态
     * @return 设备连接状态集合
     * @throws IOException
     */
    public List<CollectSocket.SocketItem> getDeivceConnections() throws IOException {

        HashMap<String,CollectSocket.SocketItem> relays=new HashMap<>();
        for(FogArea fogArea:fogAreaDAO.getFogAreas(Department.AllTag))
        {
            relays.put(Integer.toString(fogArea.getJdqbsm()),null);
        }

        CollectSocket collectSocket = new CollectSocket();
        byte[] buffer=collectSocket.request();
        SocketResult sr = SocketTask.ProtocolHandler.sendTcp(collectSocket.getId()+1,collectSocket.getStampTime(),buffer);
        List<CollectSocket.SocketItem> list = new ArrayList<>();

        if (sr.getResult() == SendResult.Success) {
            List<CollectSocket.SocketItem> items = collectSocket.handle(sr.getReceive());
            for (CollectSocket.SocketItem item : items) {
               if(relays.containsKey(item.getTag())&&relays.get(item.getTag())==null)
               {
                   item.setType(DeviceType.Relay);
                   list.add(item);
                   relays.put(item.getTag(),item);
               }
            }
        }
        Collections.sort(list, Comparator.comparing(CollectSocket.SocketItem::getTag));
        return list;
    }

    /**
     * 查询雾区中的控制器运行参数和太阳能信息
     *
     * @param fogArea  雾区
     * @return 控制器运行参数集合
     * @throws IOException
     */
    public void queryRealControllers(FogArea fogArea,boolean queryConfig,boolean querySolarEnergy,boolean queryTextConfig,boolean queryText,boolean onlyManual,String joinId,StringBuilder builder) throws IOException {

        boolean needLog=false;
        if(builder==null)
        {
            needLog=true;
            builder=new StringBuilder();
            joinId=UUID.randomUUID().toString();
        }
        List<Controller> controllers = controllerDAO.getControllers(fogArea.getWqbm());
        for (Controller controller : controllers) {

            //运行状态
            if(queryConfig)
            {
                controllerService.queryControllerConfig(controller,builder,joinId);
            }
            //太阳能
            if(querySolarEnergy)
            {
                controllerService.querySolarEnergy(controller,builder,joinId);
            }
            //文字
            if(queryText)
            {
               controllerService.queryControllerText(controller,onlyManual,builder,joinId);

                //如果只查询了手动要补足后面的
                if(onlyManual)
                {
                    FogArea f=FogAreaMap.get(fogArea.getWqbm());
                    if(f.getControllers_zt()!=null)
                    {
                        for(Controller c:f.getControllers_zt())
                        {
                            if(controller.getKzqbm()==c.getKzqbm())
                            {
                                for(int i=1;i<c.getControllerTexts().size();++i)
                                {
                                    controller.getControllerTexts().add(c.getControllerTexts().get(i));
                                }
                                break;
                            }
                        }
                    }
                }
            }
            //文字配置
            if(queryTextConfig)
            {
                controllerService.queryControllerTextConfig(controller,builder,joinId);
            }
        }

        fogArea.setControllers_zt(controllers);

        //全部查询才更新缓存
        if(queryConfig&&querySolarEnergy&&queryText&&queryTextConfig)
        {
            FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
            if(fogAreaCache!=null) {
                fogAreaCache.setControllers_zt(fogArea.getControllers_zt());
            }
        }

        if(needLog)
        {
            logService.insertSystemLog(Token.SystemToken,SystemLogType.QueryControllerConfig,builder.toString(),joinId);
        }
    }

    public List<Controller> queryControllersTimerConfig(int wqbm) throws IOException {
        List<Controller> controllers = controllerDAO.getControllers(wqbm);
        List<Controller> result=new ArrayList<>();
        for (Controller controller : controllers) {
            Controller queryController=controllerService.queryControllerTimer(controller.getKzqdk(),controller.getKzqbsm());
            queryController.setKzqmc(controller.getKzqmc());
            result.add(queryController);
        }
        return result;
    }

    public List<ActionResult> setControllersTimerConfig(Controller timerController) throws IOException {
        List<Controller> controllers = controllerDAO.getControllers(timerController.getWqbm());
        List<ActionResult> results = new ArrayList<>();
        String joinId=UUID.randomUUID().toString();
        StringBuilder builder=new StringBuilder();

        for (Controller controller : controllers) {
            timerController.setKzqmc(controller.getKzqmc());
            timerController.setKzqbsm(controller.getKzqbsm());
            timerController.setKzqdk(controller.getKzqdk());
            builder.append(String.format("设置GPS时间参数->%s\n",timerController.getKzqmc()));
            for(int i=1;i<=3;++i)
            {
                timerController.setTimeIndex(i);

                SetControllerTimer setControllerTimer=new SetControllerTimer();
                byte[] buffer = setControllerTimer.toBuffer(timerController.getKzqbsm(),timerController);
                SocketResult result= controllerService.sendShoot(timerController.getKzqdk(),timerController.getKzqbsm(), buffer,setControllerTimer.getId(),joinId);
                ActionResult actionResult=new ActionResult();
                actionResult.setName(timerController.getKzqmc());
                actionResult.setKey(i);
                actionResult.setCzjg(result.getResult().ordinal());
                results.add(actionResult);
                if(i==1)
                {
                    builder.append(String.format("时段1 结果:%s 开始小时:%d 开始分:%d 停止小时:%d 停止分钟:%d 月:%d 日:%d 雾灯控制:%d 雾灯亮度:%d 占空比:%d 红灯延时:%d 盲区延时:%d 红色警示灯组数量:%d 是否启用星历:%b\n"
                            ,result.getResult().toString()
                            ,timerController.getStartHour1()
                            ,timerController.getStartMinute1()
                            ,timerController.getStopHour1()
                            ,timerController.getStopMinute1()
                            ,timerController.getMonth1()
                            ,timerController.getDay1()
                            ,timerController.getWdkz1()
                            ,timerController.getWdld1()
                            ,timerController.getZkb1()
                            ,timerController.getHdys1()
                            ,timerController.getMqys1()
                            ,timerController.getHsjsdzsl1()
                            ,timerController.isSfsyxl1()

                    ));
                }
                else if(i==2)
                {
                    builder.append(String.format("时段2 结果:%s 开始小时:%d 开始分:%d 停止小时:%d 停止分钟:%d 月:%d 日:%d 雾灯控制:%d 雾灯亮度:%d 占空比:%d 红灯延时:%d 盲区延时:%d 红色警示灯组数量:%d 是否启用星历:%b\n"
                            ,result.getResult().toString()
                            ,timerController.getStartHour2()
                            ,timerController.getStartMinute2()
                            ,timerController.getStopHour2()
                            ,timerController.getStopMinute2()
                            ,timerController.getMonth2()
                            ,timerController.getDay2()
                            ,timerController.getWdkz2()
                            ,timerController.getWdld2()
                            ,timerController.getZkb2()
                            ,timerController.getHdys2()
                            ,timerController.getMqys2()
                            ,timerController.getHsjsdzsl2()
                            ,timerController.isSfsyxl2()

                    ));
                }
                else if(i==3)
                {
                    builder.append(String.format("时段3 结果:%s 开始小时:%d 开始分:%d 停止小时:%d 停止分钟:%d 月:%d 日:%d 雾灯控制:%d 雾灯亮度:%d 占空比:%d 红灯延时:%d 盲区延时:%d 红色警示灯组数量:%d 是否启用星历:%b\n"
                            ,result.getResult().toString()
                            ,timerController.getStartHour3()
                            ,timerController.getStartMinute3()
                            ,timerController.getStopHour3()
                            ,timerController.getStopMinute3()
                            ,timerController.getMonth3()
                            ,timerController.getDay3()
                            ,timerController.getWdkz3()
                            ,timerController.getWdld3()
                            ,timerController.getZkb3()
                            ,timerController.getHdys3()
                            ,timerController.getMqys3()
                            ,timerController.getHsjsdzsl3()
                            ,timerController.isSfsyxl3()

                    ));
                }
            }
        }
        logService.insertSystemLog(Token.SystemToken,SystemLogType.SetControllerTimeConfig,builder.toString(),joinId);
        return results;
    }

    public void updateFogAreaLightConfig(String token,FogArea fogArea)
    {
        fogAreaDAO.updateFogAreaLightConfig(fogArea);
        if(fogArea.getControllers()!=null)
        {
            for (Controller controller:fogArea.getControllers()) {
                controllerDAO.updateControllerLightConfig(controller);
            }
        }
    }

        /**
         * 设置雾区中的控制器运行参数
         *
         * @param token   token
         * @param fogArea 雾区
         * @return 第一个参数表示设置后当前雾区的运行模式和参数，第二个参数表示操作结果集合
         * 因为在设置自动模式的时候，如果当前雾区存在方案配置，则以方案为主，并不会执行自动方案，所以需要返回雾区的信息
         * 前台显示也应以返回值为主，而不是显示自动
         * @throws IOException
         */
    public List<ActionResult> setControllersConfig(String token, FogArea fogArea) throws IOException {
        String joinId=UUID.randomUUID().toString();
        StringBuilder contentBuilder=new StringBuilder();

        contentBuilder.append(String.format(
                "雾区编码:%d\n传入->工作模式:%d 手动时长:%s 控制策略:%d 雾灯亮度等级:%d 闪烁频率:%d 占空比:%d 雾灯控制:%d 雾灯亮度:%d 亮灯时长:%d 灭灯时长:%d 红灯延时:%d 盲区延时:%d 红色警示灯数量:%d\n",
                fogArea.getWqbm(),fogArea.getGzms(),fogArea.getCxsj(),fogArea.getKzcl(),fogArea.getWdlddj(),fogArea.getSspl(),fogArea.getZkb(),fogArea.getWdkz(),fogArea.getWdld(),fogArea.getLdsc(),fogArea.getMdsc(),fogArea.getHdys(),fogArea.getMqys(),fogArea.getHsjsdzsl()));

        //删除所有临时方案
        holidayDAO.deleteHolidays(fogArea.getWqbm());
        //是否为手动状态，不能用fogArea.getGzms，因为分析完就变了

        if(fogArea.getGzms()==FogAreaWorkMode.Manual)
        {
            //手动模式有手动时长的要设置临时方案
            if(Integer.parseInt(fogArea.getCxsj())>0)
            {
                Holiday holiday=new Holiday();
                holiday.setWqbm(fogArea.getWqbm());
                holiday.setFamc("手动模式");
                //假日方案精确到秒，所以要减一秒，否则可能在下面分析时出现时间未到的情况
                holiday.setKssj(new Timestamp(System.currentTimeMillis()-1000));
                holiday.setCxsj(Integer.parseInt(fogArea.getCxsj()));

                holiday.setKzcl(fogArea.getKzcl());
                holiday.setWdlddj(fogArea.getWdlddj());
                holiday.setSspl(fogArea.getSspl());
                holiday.setZkb(fogArea.getZkb());

                holiday.setWdkz(fogArea.getWdkz());
                holiday.setWdld(fogArea.getWdld());
                holiday.setLdsc(fogArea.getLdsc());
                holiday.setMdsc(fogArea.getMdsc());
                holiday.setHdys(fogArea.getHdys());
                holiday.setMqys(fogArea.getMqys());
                holiday.setHsjsdzsl(fogArea.getHsjsdzsl());
                holidayDAO.insertHoliday(holiday);
            }
        }

        //更新模式和参数字段
        fogAreaDAO.updateFogAreaConfig(fogArea);

        //分析当前执行参数
        analysisWorkMode(fogArea);
        contentBuilder.append(String.format("分析->工作模式:%d 手动时长:%s 控制策略:%d 雾灯亮度等级:%d 闪烁频率:%d 占空比:%d 雾灯状态:%d 雾灯亮度:%d 亮灯时长:%d 灭灯时长:%d 红灯延时:%d 盲区延时:%d 红色警示灯数量:%d\n",
                fogArea.getGzms(),fogArea.getCxsj(),fogArea.getKzcl(),fogArea.getWdlddj(),fogArea.getSspl(),fogArea.getZkb(),fogArea.getWdkz(),fogArea.getWdld(), fogArea.getLdsc(), fogArea.getMdsc(),
                fogArea.getHdys(), fogArea.getMqys(), fogArea.getHsjsdzsl()));

        boolean isManual=fogArea.getGzms()==FogAreaWorkMode.Manual||fogArea.getGzms()==FogAreaWorkMode.Temporary;

        //手动才查询文字参数，否则只填充controllers_zt
        queryRealControllers(fogArea, false, false, isManual, false, false, joinId, contentBuilder);

        List<ActionResult> list = new ArrayList<>();
        for (Controller controller : fogArea.getControllers_zt()) {
            ActionResult actionResult = new ActionResult();
            actionResult.setKey(controller.getKzqbsm());
            actionResult.setName(controller.getKzqmc());
            if (fogArea.getWdkz() == ControllerWorkMode.Restart) {
                SocketResult sr = controllerService.restartController(controller.getKzqdk(),controller.getKzqbsm(),joinId);
                actionResult.setCzjg(sr.getResult().ordinal());
                contentBuilder.append(String.format(" 重启 %s",sr.getResult()));
            } else {

                controller.setWdkz(fogArea.getWdkz());
                controller.setWdld(fogArea.getWdld());
                controller.setLdsc(fogArea.getLdsc());
                controller.setMdsc(fogArea.getMdsc());
                controller.setHdys(fogArea.getHdys());
                controller.setMqys(fogArea.getMqys());
                controller.setHsjsdzsl(fogArea.getHsjsdzsl());

                SendResult result1 = controllerService.setControllerConfig(controller,contentBuilder,joinId);
                //下发成功，更新用于同步对比的缓存
                if (result1 == SendResult.Success) {
                    ControllerConfigMap.put(controller.getKzqbm(), controller);
                }

                //手动模式才下发文字和文字参数
                if(isManual)
                {
                    ArrayList<ControllerText> controllerTexts=new ArrayList<>();
                    ControllerText controllerText=new ControllerText();
                    controllerText.setLxbh(0);
                    controllerText.setWdwz(fogArea.getWdwz());
                    controllerTexts.add(controllerText);
                    controller.setControllerTexts(controllerTexts);
                    Tuple<Integer,Integer> result2=controllerService.setControllerText(controller,true,contentBuilder,joinId);

                    controller.setCfsd(fogArea.getCfsd());

                    if(fogArea.isForceTextConfig())
                    {
                        controller.setSfgs(fogArea.getSfgs());
                        controller.setDscf(fogArea.getDscf());
                        controller.setQxcf(fogArea.getQxcf());
                        controller.setWzmk2(fogArea.getWzmk2());
                        controller.setWzmk1(fogArea.getWzmk1());
                        controller.setWdgz(fogArea.getWdgz());
                    }
                    else
                    {
                        if(fogArea.getWdgz()==0&&fogArea.getWzmk1()==0)
                        {
                            controller.setSfgs(fogArea.getSfgs());
                            controller.setDscf(fogArea.getDscf());
                            controller.setQxcf(fogArea.getQxcf());
                            //controller.setWzmk2(fogArea.getWzmk2());
                            controller.setWzmk1(fogArea.getWzmk1());
                            controller.setWdgz(fogArea.getWdgz());
                        }
                        else if(fogArea.getWdgz()==0&&fogArea.getWzmk1()==1)
                        {
                            //controller.setSfgs(fogArea.getSfgs());
                            //controller.setDscf(fogArea.getDscf());
                            //controller.setQxcf(fogArea.getQxcf());
                            //controller.setWzmk2(fogArea.getWzmk2());
                            controller.setWzmk1(fogArea.getWzmk1());
                            controller.setWdgz(fogArea.getWdgz());
                        }
                        else if(fogArea.getWdgz()==1&&fogArea.getWzmk2()==0)
                        {
                            controller.setSfgs(fogArea.getSfgs());
                            controller.setDscf(fogArea.getDscf());
                            controller.setQxcf(fogArea.getQxcf());
                            controller.setWzmk2(fogArea.getWzmk2());
                            //controller.setWzmk1(fogArea.getWzmk1());
                            controller.setWdgz(fogArea.getWdgz());
                        }
                        else if(fogArea.getWdgz()==0&&fogArea.getWzmk2()==1)
                        {
                            //controller.setSfgs(fogArea.getSfgs());
                            //controller.setDscf(fogArea.getDscf());
                            //controller.setQxcf(fogArea.getQxcf());
                            controller.setWzmk2(fogArea.getWzmk2());
                            //controller.setWzmk1(fogArea.getWzmk1());
                            controller.setWdgz(fogArea.getWdgz());
                        }
                    }
                    controller.setGs_Lddj(fogArea.getGs_Lddj());
                    controller.setGs_Sspl(fogArea.getGs_Sspl());
                    controller.setGs_Zkb(fogArea.getGs_Zkb());

                    SendResult result3=controllerService.setControllerTextConfig(controller,contentBuilder,joinId);

                    if(result1==SendResult.Success&&result3==SendResult.Success&&result2.getItem2()==0)
                    {
                        actionResult.setCzjg(0);
                    }
                    else
                    {
                        actionResult.setCzjg(1);
                    }
                }
                //自动模式下发手动空文字
                else
                {
                    ArrayList<ControllerText> controllerTexts=new ArrayList<>();
                    ControllerText controllerText=new ControllerText();
                    controllerText.setLxbh(0);
                    controllerText.setWdwz(null);
                    controllerTexts.add(controllerText);
                    controller.setControllerTexts(controllerTexts);
                    Tuple<Integer,Integer> result2=controllerService.setControllerText(controller,true,contentBuilder,joinId);
                    if(result1==SendResult.Success&&result2.getItem2()==0)
                    {
                        actionResult.setCzjg(0);
                    }
                    else
                    {
                        actionResult.setCzjg(1);
                    }
                }
            }
            list.add(actionResult);
        }

        queryRealControllers(fogArea,true,true,true,true,true,joinId,contentBuilder);

        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            FogAreaServer.sendAll(logService,fogAreaCache,"设置");
        }
        logService.insertSystemLog(token,SystemLogType.SetControllerConfig,contentBuilder.toString(),joinId);
        return list;
    }

    /**
     * 删除雾区及相关设备
     *
     * @param fogArea wqbm 雾区编码
     */
    @Transactional
    public void deleteFogArea(FogArea fogArea) {
        List<Controller> controllers = controllerDAO.getControllers(fogArea.getWqbm());
        fogAreaDAO.deleteFogArea(fogArea.getWqbm());
        controllerDAO.deleteControllers(fogArea.getWqbm());
        linkDeviceDAO.deleteLinkDevices(fogArea.getWqbm());
        for (Controller controller : controllers) {
            visibilityDAO.deleteVisibilities(controller.getKzqbm());
        }
        programDAO.deleteProgram(fogArea.getWqbm());
        holidayDAO.deleteHoliday(fogArea.getWqbm());
    }

    /**
     * 刷新雾区设备信息并保存到缓存
     */
    public void refreshFogAreaCaches() {

        for (FogArea fogArea : fogAreaDAO.getFogAreas(Department.AllTag)) {
            try
            {
                Date start=new Date();
                String joinId=UUID.randomUUID().toString();
                StringBuilder contentBuilder = new StringBuilder();
                //初始化缓存
                if (!FogAreaMap.containsKey(fogArea.getWqbm())) {

                    //路面和天气状态
                    //部分控制器因为无法得到天气通知，所以必须在这里设置默认值
                    fogArea.setLmzt("-");

                    //方案信息
                    fogArea.setFamc("-");
                    fogArea.setCxsj("-");
                    fogArea.setKssj("-");

                    fogArea.setGxsj("-");

                    FogAreaMap.put(fogArea.getWqbm(), fogArea);
                }

                //能见度检测仪
                Visibility visibility = visibilityDAO.getVisibility(fogArea.getWqbm());
                //未找到雾区的能见度检测仪
                if (visibility == null) {
                    fogArea.setJcysbzt(VisibilityDeviceStatus.Unconfig);
                    //能见度
                    fogArea.setNjd(-1);
                    fogArea.setNjdyfz(-1);
                    fogArea.setNjdsfz(-1);

                    //天气
                    fogArea.setTqdm(-1);
                }
                //有能见度检测仪
                else {
                    fogArea.setJcybsm(visibility.getKzqbsm());
                    fogArea.setJcybh(visibility.getJcybh());
                    fogArea.setJcydk(visibility.getKzqdk());
                    SocketResult<FogArea> temp = controllerService.queryVisibility(fogArea.getJcydk(),fogArea.getJcybsm(),joinId);

                    //查询失败
                    if (temp.getData()==null) {
                        fogArea.setJcysbzt(VisibilityDeviceStatus.NetError);
                        //能见度
                        fogArea.setNjd(-1);
                        fogArea.setNjdyfz(-1);
                        fogArea.setNjdsfz(-1);

                        //天气
                        fogArea.setTqdm(-1);
                    }
                    //查询成功
                    else {

                        fogArea.setJcysbzt(VisibilityDeviceStatus.Noraml);

                        //能见度
                        fogArea.setNjd(temp.getData().getNjd());
                        fogArea.setNjdyfz(temp.getData().getNjdyfz());
                        fogArea.setNjdsfz(temp.getData().getNjdsfz());

                        //天气
                        fogArea.setTqdm(temp.getData().getTqdm());
                    }
                }
                setVisibilityCache(fogArea);

                //继电器
                if(fogArea.getJdqbsm()==0)
                {
                    fogArea.setJdqgzms(RelayControlMode.Error);
                }
                else
                {
                    SocketResult<Integer> sr=controllerService.queryRelayStatus(fogArea.getJdqbsm(),joinId);
                    //查询继电器状态
                    fogArea.setJdqgzms(sr.getData());
                }
                setRelayCache(fogArea);
                contentBuilder.append(String.format("雾区:%s 能见度检测仪:%d->%d 继电器:%d\n", fogArea.getWqmc(),fogArea.getJcybsm(), fogArea.getNjd(),fogArea.getJdqbsm()));

                //更新时间
                fogArea.setGxsj(new SimpleDateFormat("HH:mm:ss").format(new Date()));
                setFogAreaStatusCache(fogArea);

                Date end = new Date();
                contentBuilder.append(String.format("耗时:%.3fs", (end.getTime() - start.getTime()) / 1000.0));
                logService.insertSystemLog(Token.SystemToken, SystemLogType.QueryFogAreas,contentBuilder.toString(),joinId);
            }
            catch (Exception ex)
            {
                logService.insertExceptionLog(ex);
            }
        }
    }

    private List<Controller> queryLightControllers(FogArea fogArea,StringBuilder contentBuilder,String joinId) throws IOException {
        List<Controller> controllers=controllerService.getControllers(fogArea.getWqbm());
        for (Controller controller:controllers)
        {
            if(fogArea.getFwzq()<=0)
            {
                controller.setJcld(false);
                controller.setGgsz(0);
                contentBuilder.append(String.format("控制器:%s 雾区不访问，略过 \n", controller.getKzqmc()));
            }
            else {
                if(controller.isJcld())
                {
                    SocketResult<Integer> result=controllerService.queryLight(controller.getKzqdk(),controller.getKzqbsm(),joinId);
                    if(result.getResult()==SendResult.Success)
                    {
                        controller.setGgsz(result.getData());
                        contentBuilder.append(String.format("控制器:%s 光感数据 %d \n", controller.getKzqmc(),result.getData()));
                    }
                    else
                    {
                        controller.setGgsz(-1);
                        contentBuilder.append(String.format("控制器:%s 网络异常 %d \n",controller.getKzqmc(), result.getResult().ordinal()));
                    }
                }
                else
                {
                    controller.setGgsz(0);
                    contentBuilder.append(String.format("控制器:%s 不检查，略过 \n", controller.getKzqmc()));
                }
            }
        }
        return controllers;
    }

    public void calculateFogAreasLight(int minute){

        for (FogArea fogArea : fogAreaDAO.getFogAreas(Department.AllTag)) {
            try
            {
                if(fogArea.getFwzq()==0)
                {
                    List<Controller> controllers=controllerService.getControllers(fogArea.getWqbm());
                    for (Controller controller:controllers)
                    {
                        controller.setJcld(false);
                    }
                    fogArea.setTempQrcs(0);
                    fogArea.setTempKdfz(false);
                    fogArea.setControllers(controllers);
                    setLightCache(fogArea);
                }
                else if(minute%fogArea.getFwzq()==0)
                {
                    FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
                    if(fogAreaCache==null)
                    {
                        continue;
                    }
                    String joinId=UUID.randomUUID().toString();
                    StringBuilder contentBuilder = new StringBuilder();
                    contentBuilder.append(String.format("雾区:%s\n", fogArea.getWqmc()));
                    List<Controller> controllers=queryLightControllers(fogArea,contentBuilder,joinId);
                    //有效的数据集合
                    List<Integer> values=new ArrayList<>();
                    boolean hasHigh=false;
                    for (Controller controller:controllers)
                    {
                        if(controller.getGgsz()>=0x20)
                        {
                            hasHigh=true;
                        }
                        if(controller.getGgsz()>0)
                        {
                            values.add(controller.getGgsz());
                        }
                    }
                    //有效值
                    int validValue=0;
                    //有效个数
                    int validCount=0;
                    //结果值
                    int value=0;
                    //最大值
                    int max=0;
                    //最小值
                    int min=Integer.MAX_VALUE;
                    for (Integer v :  values) {
                        if(hasHigh&&v<=0x01)
                        {
                            continue;
                        }
                        else
                        {
                            validValue+=v;
                            validCount+=1;
                            if(v<min)
                            {
                                min=v;
                            }
                            if(v>max)
                            {
                                max=v;
                            }
                        }
                    }
                    if(validCount>0)
                    {
                        if(validCount>=3)
                        {
                            value=(validValue-min-max)/(validCount-2);
                        }
                        else if(validCount>0)
                        {
                            value=validValue/validCount;
                        }

                        if(value<=fogArea.getKdfz())
                        {
                            if(fogAreaCache.isTempKdfz())
                            {
                                fogArea.setTempQrcs(fogAreaCache.getTempQrcs()+1);
                            }
                            else
                            {
                                fogArea.setTempQrcs(1);
                            }
                            fogArea.setTempKdfz(true);
                            contentBuilder.append(String.format("光感度:%d 开灯阀值:%d 关灯阀值:%d 当前阀值:%s 访问周期:%d 需要确认次数:%d 已经确认次数:%d \n",value,fogArea.getKdfz(),fogArea.getGdfz(),"开灯",fogArea.getFwzq(),fogArea.getQrcs(),fogAreaCache.getTempQrcs()));
                        }
                        else if(value>=fogArea.getGdfz())
                        {
                            if(fogAreaCache.isTempKdfz())
                            {
                                fogArea.setTempQrcs(1);
                            }
                            else
                            {
                                fogArea.setTempQrcs(fogAreaCache.getTempQrcs()+1);
                            }
                            fogArea.setTempKdfz(false);
                            contentBuilder.append(String.format("光感度:%d 开灯阀值:%d 关灯阀值:%d 当前阀值:%s 访问周期:%d 需要确认次数:%d 已经确认次数:%d \n",value,fogArea.getKdfz(),fogArea.getGdfz(),"关灯",fogArea.getFwzq(),fogArea.getQrcs(),fogAreaCache.getTempQrcs()));
                        }
                        else
                        {
                            fogArea.setTempQrcs(0);
                            fogArea.setTempKdfz(false);
                            contentBuilder.append(String.format("光感度:%d 开灯阀值:%d 关灯阀值:%d 当前阀值:%s 访问周期:%d 需要确认次数:%d 已经确认次数:%d \n",value,fogArea.getKdfz(),fogArea.getGdfz(),"无",fogArea.getFwzq(),fogArea.getQrcs(),fogAreaCache.getTempQrcs()));
                        }
                    }
                    else
                    {
                        fogArea.setTempQrcs(0);
                        fogArea.setTempKdfz(false);
                    }
                    fogArea.setControllers(controllers);
                    setLightCache(fogArea);
                    logService.insertSystemLog(Token.SystemToken, SystemLogType.HandleLight,contentBuilder.toString(),joinId);
                }
            }
            catch (Exception ex)
            {
                logService.insertExceptionLog(ex);
            }
        }
    }

    /**
     * 比对雾区和控制器参数
     *
     * @param controller2 控制器
     * @return 返回true表示同步，返回false表示未同步
     */
    private boolean compareConfig(Controller controller1, Controller controller2) {

        return controller1.getWdkz() == controller2.getWdkz() &&
               controller1.getWdld() == controller2.getWdld() &&
               controller1.getLdsc() == controller2.getLdsc() &&
               controller1.getMdsc() == controller2.getMdsc() &&
               controller1.getMqys() == controller2.getMqys() &&
               controller1.getHdys() == controller2.getHdys();
    }

    /**
     * 分析雾区的工作模式和控制状态并且会更新缓存
     * @param fogArea 雾区
     */
    private void analysisWorkMode(FogArea fogArea) {

        if(fogArea.getWdkz()==ControllerWorkMode.Restart)
        {
            return;
        }


        Calendar now = Calendar.getInstance();
        //表示现在是否已经分析出方案
        boolean hasProgram = false;

        //分析是否是手动模式
        List<Holiday> holidays = holidayDAO.getHolidays(fogArea.getWqbm());
        for (Holiday holiday : holidays) {
            Calendar start = Calendar.getInstance();
            start.setTime(holiday.getKssj());
            start.set(Calendar.YEAR, now.get(Calendar.YEAR));

            Calendar end = Calendar.getInstance();
            end.setTime(start.getTime());
            end.add(Calendar.MINUTE, holiday.getCxsj());

            //判断时间是否覆盖当前
            if (start.getTimeInMillis() <= now.getTimeInMillis() && end.getTimeInMillis() > now.getTimeInMillis()) {

                //如果有多个方案覆盖了，就是方案冲突
                if (hasProgram) {
                    fogArea.setFact(true);
                    fogArea.setFamc("-");
                    fogArea.setKssj("-");
                    fogArea.setCxsj("-");
                    break;
                } else {
                    hasProgram = true;
                    fogArea.setFact(false);
                    fogArea.setFamc(holiday.getFamc());
                    fogArea.setKssj(new SimpleDateFormat("MM-dd HH:mm").format(holiday.getKssj()));
                    fogArea.setCxsj(String.valueOf(holiday.getCxsj()));

                    fogArea.setKzcl(holiday.getKzcl());
                    fogArea.setSspl(holiday.getSspl());
                    fogArea.setZkb(holiday.getZkb());
                    fogArea.setWdlddj(holiday.getWdlddj());

                    fogArea.setWdkz(holiday.getWdkz());
                    fogArea.setWdld(holiday.getWdld());
                    fogArea.setLdsc(holiday.getLdsc());
                    fogArea.setMdsc(holiday.getMdsc());
                    fogArea.setHdys(holiday.getHdys());
                    fogArea.setMqys(holiday.getMqys());
                    fogArea.setHsjsdzsl(holiday.getHsjsdzsl());
                }
            }
        }
        //定时手动
        if(hasProgram)
        {
            fogArea.setGzms(FogAreaWorkMode.Temporary);
        }
        //持续手动不用进行任何处理
        //自动
        else if(fogArea.getGzms()!=FogAreaWorkMode.Manual)
        {
            //分析是否是定时模式
            List<Program> programs = programDAO.getPrograms(fogArea.getWqbm(), ProgramStatus.Enable);
            for (Program program : programs) {
                boolean isFirstSunday = (now.getFirstDayOfWeek() == Calendar.SUNDAY);
                int i = now.get(Calendar.DAY_OF_WEEK);
                if(isFirstSunday){
                    i = i - 1;
                    if(i == 0){
                        i = 7;
                    }
                }
                for (int week : program.getFaxqjh()) {
                    if (week == i) {
                        Calendar start = Calendar.getInstance();
                        start.setTime(program.getKssj());
                        start.set(Calendar.YEAR, now.get(Calendar.YEAR));
                        start.set(Calendar.MONTH, now.get(Calendar.MONTH));
                        start.set(Calendar.DATE, now.get(Calendar.DATE));

                        Calendar end = Calendar.getInstance();
                        end.setTime(start.getTime());
                        end.add(Calendar.MINUTE, program.getCxsj());
                        if (start.getTimeInMillis() < now.getTimeInMillis() && end.getTimeInMillis() > now.getTimeInMillis()) {
                            if (hasProgram) {
                                fogArea.setFact(true);
                                fogArea.setFamc("-");
                                fogArea.setKssj("-");
                                fogArea.setCxsj("-");
                                break;
                            } else {
                                hasProgram = true;
                                fogArea.setFact(false);
                                fogArea.setFamc(program.getFamc());
                                fogArea.setKssj(new SimpleDateFormat("HH:mm").format(program.getKssj()));
                                fogArea.setCxsj(String.valueOf(program.getCxsj()));

                                fogArea.setKzcl(program.getKzcl());
                                fogArea.setSspl(program.getSspl());
                                fogArea.setZkb(program.getZkb());
                                fogArea.setWdlddj(program.getWdlddj());

                                fogArea.setWdkz(program.getWdkz());
                                fogArea.setWdld(program.getWdld());
                                fogArea.setLdsc(program.getLdsc());
                                fogArea.setMdsc(program.getMdsc());
                                fogArea.setHdys(program.getHdys());
                                fogArea.setMqys(program.getMqys());
                                fogArea.setHsjsdzsl(program.getHsjsdzsl());
                            }
                        }
                        break;
                    }
                }
            }
            FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
            //如果是定时方案要判断能见度是否超标
            //超标就是报警模式，否则就是定时
            if(hasProgram)
            {
                int warningNjd=visibilityScaleService.getWarningNjd(fogArea.getWqbm());
                int njd=0;
                if(fogAreaCache!=null)
                {
                    njd=fogAreaCache.getNjd();
                }
                //第一个判断表示配置有问题
                //第二个判断表示没有能见度数据
                //第三个判断表示未达到警告能见度
                if(warningNjd==0||njd==0||njd>warningNjd)
                {
                    fogArea.setGzms(FogAreaWorkMode.Timer);
                }
                //能见度超标
                else
                {
                    fogArea.setGzms(FogAreaWorkMode.Warning);
                    fogArea.setWdkz(ControllerWorkMode.Auto);
                    fogArea.setFact(false);
                    fogArea.setFamc("-");
                    fogArea.setKssj("-");
                    fogArea.setCxsj("-");
                }
            }
            //如果没找到任何方案就是光感或者自动模式
            else
            {
                //光感模式
                FogArea fogAreaDb=fogAreaDAO.getFogArea(fogArea.getWqbm());
                if(fogAreaDb.getQrcs()!=0
                        &&fogAreaCache.getTempQrcs()!=0
                        &&fogAreaCache.getTempQrcs()>=fogAreaDb.getQrcs())
                {
                    fogArea.setGzms(FogAreaWorkMode.Light);
                    fogArea.setFact(false);
                    fogArea.setFamc("-");
                    fogArea.setKssj("-");
                    fogArea.setCxsj("-");
                    if(fogAreaCache.isTempKdfz())
                    {
                        fogArea.setKzcl(fogAreaDb.getKd_kzcl());
                        fogArea.setSspl(fogAreaDb.getKd_sspl());
                        fogArea.setZkb(fogAreaDb.getKd_zkb());
                        fogArea.setWdlddj(fogAreaDb.getKd_wdlddj());

                        fogArea.setWdkz(fogAreaDb.getKd_wdkz());
                        fogArea.setWdld(fogAreaDb.getKd_wdld());
                        fogArea.setLdsc(fogAreaDb.getKd_ldsc());
                        fogArea.setMdsc(fogAreaDb.getKd_mdsc());
                        fogArea.setHsjsdzsl(fogAreaDb.getKd_hsjsdzsl());
                        fogArea.setHdys(fogAreaDb.getKd_hdys());
                        fogArea.setMqys(fogAreaDb.getKd_mqys());
                    }
                    else
                    {
                        fogArea.setWdkz(ControllerWorkMode.Auto);
                    }
                }
                //自动模式
                else
                {
                    fogArea.setGzms(FogAreaWorkMode.Auto);
                    fogArea.setKzcl(ControlStrategy.Unknown);
                    fogArea.setWdkz(ControllerWorkMode.Auto);
                    fogArea.setFact(false);
                    fogArea.setFamc("-");
                    fogArea.setKssj("-");
                    fogArea.setCxsj("-");
                }
            }
        }


        //计算策略的数值
        if(fogArea.getKzcl()==ControlStrategy.Custom
                ||fogArea.getKzcl()==ControlStrategy.Unknown)
        {
            fogArea.setWdld(fogArea.getWdld());
            fogArea.setLdsc(fogArea.getLdsc());
            fogArea.setMdsc(fogArea.getMdsc());
        }
        else
        {
            try
            {
                fogArea.setWdld(controllerService.getWdld(fogArea.getWdlddj()));
            }
            catch(Exception e)
            {
                fogArea.setWdld(0);
            }
            Tuple<Integer,Integer> t=controllerService.getLdsc(fogArea.getSspl(),fogArea.getZkb());
            fogArea.setLdsc(t.getItem1());
            fogArea.setMdsc(t.getItem2());
        }
        fogArea.setGzmssm(codeService.getCodeValue(CodeType.Gzms,fogArea.getGzms()));
        fogArea.setWdkzsm(codeService.getCodeValue(CodeType.Wdkz,fogArea.getWdkz()));
        Strategy cacheStrategy=strategyDAO.getStrategy(fogArea.getKzcl());
        fogArea.setKzclsm(cacheStrategy==null
                ? "-"
                : cacheStrategy.getClmc());
        fogArea.setSsplsm(codeService.getCodeValue(CodeType.Sspl,fogArea.getSspl()));
        fogArea.setZkbsm(codeService.getCodeValue(CodeType.Zkb,fogArea.getZkb()));
        fogArea.setWdlddjsm(codeService.getCodeValue(CodeType.Wdlddj,fogArea.getWdlddj()));

        setWorkModeCache(fogArea);
    }

    /**
     * 同步雾区
     *
     * @throws IOException
     */
    public void syncFogAreas(boolean forced){

        for (FogArea fogArea : fogAreaDAO.getFogAreas(Department.AllTag)) {
            try
           {
               Date start = new Date();
               String joinId=UUID.randomUUID().toString();
               StringBuilder contentBuilder = new StringBuilder();
               //分析方案
               analysisWorkMode(fogArea);

               if (fogArea.getWdkz() == ControllerWorkMode.Restart) {
                   contentBuilder.append(String.format("%s\n重启\n", fogArea.getWqmc()));
                   List<Controller> controllers = controllerDAO.getControllers(fogArea.getWqbm());
                   for (Controller controller : controllers) {
                       SocketResult sr = controllerService.restartController(controller.getKzqdk(),controller.getKzqbsm(),joinId);
                       contentBuilder.append(String.format("%d %s\n", controller.getKzqbsm(), sr.getResult()));

                   }
               } else {
                   contentBuilder.append(String.format("%s\n工作模式:%s 控制策略 %s 雾灯状态:%s 雾灯亮度:%d 亮灯时长:%d 灭灯时长:%d 红灯延时:%d 盲区延时:%d 红色警示灯数量:%d\n",
                           fogArea.getWqmc(), fogArea.getGzmssm(), fogArea.getKzclsm(),fogArea.getWdkzsm(), fogArea.getWdld(), fogArea.getLdsc(), fogArea.getMdsc(),
                           fogArea.getHdys(), fogArea.getMqys(), fogArea.getHsjsdzsl()));

                   List<Controller> controllers = controllerDAO.getControllers(fogArea.getWqbm());
                   for (Controller controller : controllers) {
                       controller.setWdkz(fogArea.getWdkz());
                       controller.setWdld(fogArea.getWdld());
                       controller.setLdsc(fogArea.getLdsc());
                       controller.setMdsc(fogArea.getMdsc());
                       controller.setHdys(fogArea.getHdys());
                       controller.setMqys(fogArea.getMqys());
                       controller.setHsjsdzsl(fogArea.getHsjsdzsl());

                       if(forced)
                       {
                           SendResult sr = controllerService.setControllerConfig(controller,contentBuilder,joinId);
                           if (sr == SendResult.Success) {
                               ControllerConfigMap.put(controller.getKzqbm(), controller);
                           }
                           contentBuilder.append(String.format("%d %s 强制下发\n", controller.getKzqbsm(), sr));
                       }
                       else
                       {
                           Controller temp = ControllerConfigMap.get(controller.getKzqbm());
                           if (temp == null || !compareConfig(temp, controller)) {
                               SendResult sr = controllerService.setControllerConfig(controller,contentBuilder,joinId);
                               if (sr == SendResult.Success) {
                                   ControllerConfigMap.put(controller.getKzqbm(), controller);
                               }
                               contentBuilder.append(String.format("%d %s\n", controller.getKzqbsm(), sr));

                           } else {
                               contentBuilder.append(String.format("%d 已经同步\n", controller.getKzqbsm()));
                           }
                       }
                   }
               }

               queryRealControllers(fogArea,true,true,true,true,false,joinId,contentBuilder);

               FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
               if(fogAreaCache!=null)
               {
                   FogAreaServer.sendAll(logService,fogAreaCache,"同步");
               }
               Date end = new Date();
               contentBuilder.append(String.format("耗时:%.3fs", (end.getTime() - start.getTime()) / 1000.0));
               logService.insertSystemLog(Token.SystemToken, SystemLogType.SyncFogAreas,contentBuilder.toString(),joinId);
           }
           catch (Exception ex)
           {
               logService.insertExceptionLog(ex);
           }
        }

    }


    /**
     * 统计能见度
     */
    public void statisticsVisibility() throws IOException {

        StringBuilder contentBuilder = new StringBuilder();
        String joinId=UUID.randomUUID().toString();
        for (FogArea fogArea : fogAreaDAO.getFogAreas(Department.AllTag)) {

            //查询雾区的能见度检测仪
            Visibility visibility = visibilityDAO.getVisibility(fogArea.getWqbm());
            //没有能见度检测仪
            if (visibility == null) {
                contentBuilder.append(String.format("%s 未配置能见度检测仪\n", fogArea.getWqmc()));
            } else {
                VisibilityStatistics visibilityStatistics = new VisibilityStatistics();
                visibilityStatistics.setWqbm(fogArea.getWqbm());
                //如果有能见度检测仪
                //首先查询缓存中是否有本次统计周期内得到的能见度信息
                Queue<VisibilityStatistics> queue = StatisticsMap.get(fogArea.getJcybsm()+"_"+fogArea.getJcydk());
                if (queue == null||queue.isEmpty()) {
                    //如果没有则主动查询一次能见度数据
                    SocketResult<FogArea> temp = controllerService.queryVisibility(visibility.getKzqdk(),visibility.getKzqbsm(),joinId);

                    if (temp.getData() == null) {
                        //如果没查到则无法统计
                        contentBuilder.append(String.format("%s 从检测仪未获取到能见度\n", fogArea.getWqmc()));
                        visibilityStatistics.setNjd(-1);
                        visibilityStatistics.setTqdm(-1);
                    } else {
                        //查询成功
                        visibilityStatistics.setNjd(temp.getData().getNjd());
                        visibilityStatistics.setTqdm(temp.getData().getTqdm());
                        contentBuilder.append(String.format("%s 从检测仪获取到能见度%d 天气代码%d\n", fogArea.getWqmc(), temp.getData().getNjd(),temp.getData().getTqdm()));
                    }
                } else {
                    //如果缓存中有数据则求平均值
                    int sum = 0;
                    for (VisibilityStatistics vs : queue) {
                        sum += vs.getNjd();
                    }
                    int value = sum / queue.size();//能见度平均值
                    //依然做异常数据判断
                    if (value <= 0) {
                        visibilityStatistics.setNjd(-1);
                        visibilityStatistics.setTqdm(-1);
                        contentBuilder.append(String.format("%s 从通知队列中未获取到能见度\n", fogArea.getWqmc()));
                    } else {
                        visibilityStatistics.setNjd(value);
                        VisibilityStatistics first=queue.peek();
                        visibilityStatistics.setTqdm(first.getTqdm());
                        contentBuilder.append(String.format("%s 从通知队列中获取到能见度%d 天气代码%d\n", fogArea.getWqmc(), value,first.getTqdm()));
                    }
                }
                if (visibilityStatistics.getNjd() != -1) {
                    visibilityStatistics.setTqdmsm(codeService.getCodeValue(CodeType.Tqdm,visibilityStatistics.getTqdm()));
                    visibilityStatisticsDAO.insertVisibilityStatistics(visibilityStatistics);
                }
            }
        }
        StatisticsMap.clear();//清空队列
        logService.insertSystemLog(Token.SystemToken, SystemLogType.StatisticsVisibility,contentBuilder.toString(),joinId);
    }


    public List<ActionResult> setVisibility(String token,FogArea fogArea) throws IOException {
        VisibilityScale visibilityScale=visibilityScaleService.getVisibilityScale(fogArea.getWqbm(), fogArea.getNjd());

        fogArea.setXjgzms(FogAreaWorkMode.Manual);
        fogArea.setXcxszxx(visibilityScale.getXcxszxx());
        fogArea.setXcxszsx(visibilityScale.getXcxszsx());
        fogArea.setDcxszxx(visibilityScale.getDcxszxx());
        fogArea.setDcxszsx(visibilityScale.getDcxszsx());
        setCameras(token,fogArea);

        fogArea.setXspgzms(FogAreaWorkMode.Manual);
        fogArea.setXsz(visibilityScale.getXsz());
        setLeds(token,fogArea);

        fogArea.setHjgzms(FogAreaWorkMode.Manual);
        fogArea.setHjyy(visibilityScale.getHjyy());
        fogArea.setHjyl(visibilityScale.getHjyl());
        setHorns(token,fogArea);

        fogArea.setGzms(FogAreaWorkMode.Manual);
        fogArea.setCxsj("5");
        fogArea.setKzcl(visibilityScale.getKzcl());
        fogArea.setSspl(visibilityScale.getSspl());
        fogArea.setZkb(visibilityScale.getZkb());
        fogArea.setWdlddj(visibilityScale.getWdlddj());

        fogArea.setWdkz(visibilityScale.getWdkz());
        fogArea.setWdld(visibilityScale.getWdld());
        fogArea.setLdsc(visibilityScale.getLdsc());
        fogArea.setMdsc(visibilityScale.getMdsc());
        fogArea.setHsjsdzsl(visibilityScale.getHsjsdzsl());
        fogArea.setHdys(visibilityScale.getHdys());
        fogArea.setMqys(visibilityScale.getMqys());

        return setControllersConfig(token,fogArea);
    }

    /**
     * 外部设备更新能见度
     * @param njdbh 能见度编号
     * @param njd 能见度
     * @param tqdm 天气代码
     * @throws IOException
     */
    public void updateOutVisibility(String njdbh,int njd,int tqdm) throws IOException {
        StringBuilder contentBuilder = new StringBuilder();
        contentBuilder.append(String.format("能见度设备编号:%s 能见度:%d\n",njdbh,njd));
        if(njd!=0)
        {
            for(Map.Entry<Integer,FogArea> entry:FogAreaMap.entrySet())
            {
                FogArea fogAreaCache=entry.getValue();
                if(fogAreaCache.getJcybh()!=null
                        &&njdbh!=null
                        &&fogAreaCache.getJcybh().equalsIgnoreCase(njdbh))
                {
                    contentBuilder.append(String.format("%s\n",fogAreaCache.getWqmc()));
                    FogArea fogArea=new FogArea();
                    fogArea.setWqbm(fogAreaCache.getWqbm());
                    fogArea.setJcysbzt(DeviceStatus.Noraml);
                    fogArea.setNjd(njd);
                    fogArea.setNjdyfz(njd);
                    fogArea.setNjdsfz(njd);
                    fogArea.setTqdm(tqdm);
                    setVisibilityCache(fogArea);
                    forwardVisibility(fogAreaCache,0);
                    addVisibilityStatistics(fogAreaCache);
                    linkDevices(fogAreaCache);
                }
            }
        }
        logService.insertSystemLog(Token.SystemToken, SystemLogType.SetVisibility,contentBuilder.toString(),null);
    }

    private void linkDevices(FogArea fogArea) throws IOException {
        //如果当前雾区的联动设备是自动，需要根据能见度等级的参数下发控制设备命令
        if(fogArea.getXspgzms()==FogAreaWorkMode.Auto)
        {
            for(LinkDevice led:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Led))
            {
                int card=Integer.parseInt(led.getTxcs());
                int speed=fogArea.getXsz();
                int size=Integer.parseInt(led.getGgxh());
                linkDeviceService.setLedSpeed(Token.SystemToken,card,speed,size,led.getSbcj(),led.getIpdz(),led.getFwdk());
            }
        }
        if(fogArea.getXjgzms()==FogAreaWorkMode.Auto)
        {
            for(LinkDevice camera:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Camera))
            {
                String cameraIp=camera.getIpdz();
                int smallLow=fogArea.getXcxszxx();
                int smallHigh=fogArea.getXcxszsx();
                int bigLow=fogArea.getDcxszxx();
                int bigHigh=fogArea.getDcxszsx();
                linkDeviceService.setCameraSpeed(Token.SystemToken,cameraIp,smallLow,smallHigh,bigLow,bigHigh);
            }
        }
        if(fogArea.getHjgzms()==FogAreaWorkMode.Auto)
        {
            for(LinkDevice horn:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Horn))
            {
                int id=Integer.parseInt(horn.getTxcs());
                int file=fogArea.getHjyy();
                int volume=fogArea.getHjyl();
                linkDeviceService.setHornMusic(Token.SystemToken,id,file,volume);
            }
        }
    }

    /**
     * 更新能见度
     * @param fogArea 雾区能见度信息
     * @throws IOException
     */
    public void updateNoticeVisibility(FogArea fogArea) throws IOException {

        if(fogArea.getNjd()==0)
        {
            return;
        }
        for(Map.Entry<Integer,FogArea> entry:FogAreaMap.entrySet())
        {
            FogArea fogAreaCache=entry.getValue();
            //找到能见度检测仪对应的雾区
            if(fogAreaCache.getJcybsm()==fogArea.getJcybsm()
                    &&fogAreaCache.getJcydk()==fogArea.getJcydk())
            {
                fogArea.setWqbm(fogAreaCache.getWqbm());
                fogArea.setJcysbzt(DeviceStatus.Noraml);
                setVisibilityCache(fogArea);
                forwardVisibility(fogAreaCache,fogAreaCache.getJcybsm());
                addVisibilityStatistics(fogAreaCache);
                linkDevices(fogAreaCache);
                break;
            }
        }
    }

    public void updateWeather(FogArea fogArea)
    {
        for(Map.Entry<Integer,FogArea> entry:FogAreaMap.entrySet())
        {
            FogArea fogAreaCache=entry.getValue();
            if(fogAreaCache.getJcybsm()==fogArea.getJcybsm()
                    &&fogAreaCache.getJcydk()==fogArea.getJcydk())
            {
                fogArea.setWqbm(fogAreaCache.getWqbm());
                setWeatherCache(fogArea);
                addWeatherStatistics(fogAreaCache);
                break;
            }
        }
    }

    public void updateRoad(FogArea fogArea)
    {
        for(Map.Entry<Integer,FogArea> entry:FogAreaMap.entrySet())
        {
            FogArea fogAreaCache=entry.getValue();
            if(fogAreaCache.getJcybsm()==fogArea.getJcybsm()
                    &&fogAreaCache.getJcydk()==fogArea.getJcydk())
            {
                fogArea.setWqbm(fogAreaCache.getWqbm());
                setRoadCache(fogArea);
                break;
            }
        }
    }

    private void addVisibilityStatistics(FogArea fogArea)
    {
        //添加能见度统计缓存数据
        if(!StatisticsMap.containsKey(fogArea.getJcybsm()+"_"+fogArea.getJcydk()))
        {
            StatisticsMap.put(fogArea.getJcybsm()+"_"+fogArea.getJcydk(),new ConcurrentLinkedQueue<>());
        }
        Queue<VisibilityStatistics> queue= StatisticsMap.get(fogArea.getJcybsm()+"_"+fogArea.getJcydk());
        VisibilityStatistics vs=new VisibilityStatistics();
        vs.setNjd(fogArea.getNjd());
        vs.setTqdm(fogArea.getTqdm());
        queue.add(vs);
    }

    private void addWeatherStatistics(FogArea fogArea)
    {
        WeatherStatistics weatherStatistics=new WeatherStatistics();
        weatherStatistics.setWqbm(fogArea.getWqbm());
        weatherStatistics.setTime(new Timestamp(System.currentTimeMillis()));
        weatherStatistics.setNjd(fogArea.getNjd());
        weatherStatistics.setNjddj(fogArea.getNjddj());
        weatherStatistics.setFs(fogArea.getFs());
        weatherStatistics.setFx(fogArea.getFx());
        weatherStatistics.setSd(fogArea.getSd());
        weatherStatistics.setWd(fogArea.getWd());
        weatherStatistics.setQy(fogArea.getQy());
        weatherStatistics.setYl(fogArea.getYl());
        weatherStatisticsDAO.insertWeatherStatistics(weatherStatistics);

    }

    /**
     * 转发能见度
     * @param fogAreaCache
     * @param jcybsm 不转发的控制器标识码
     * @throws IOException
     */
    private void forwardVisibility(FogArea fogAreaCache,int jcybsm) throws IOException {
        StringBuilder contentBuilder = new StringBuilder();
        String joinId=UUID.randomUUID().toString();
        contentBuilder.append(String.format("%s\n",fogAreaCache.getWqmc()));
        boolean hasForward=false;
        for(Controller controller:controllerDAO.getControllers(fogAreaCache.getWqbm()))
        {
            if(controller.isZfnjd()&&controller.getKzqbsm()!=jcybsm)
            {
                SendResult result=controllerService.setVisibility(fogAreaCache,controller.getKzqdk(),controller.getKzqbsm(),joinId);
                contentBuilder.append(String.format("控制器:%s 转发结果:%d\n",controller.getKzqmc(),result.ordinal()));
                hasForward=true;
            }
            else
            {
                contentBuilder.append(String.format("控制器:%s 略过\n",controller.getKzqmc()));
            }
        }
        if(hasForward)
        {
            logService.insertSystemLog(Token.SystemToken, SystemLogType.ForwardVisibility,contentBuilder.toString(),joinId);
        }

    }


    /**
     * 操作雾区中的警示灯
     * @param token token
     * @param fogArea 服务
     * @return 控制结果集合
     * @throws IOException
     */
    public List<ActionResult> setWarnings(String token, FogArea fogArea) throws IOException {

        List<ActionResult> results=new ArrayList<>();

        //手动模式需要下发
        if(fogArea.getJsdgzms()==FogAreaWorkMode.Manual)
        {
            SocketResult sr=new SocketResult();
            sr.setResult(SendResult.SendFailed);
            for(LinkDevice light:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Light))
            {
                ActionResult result=new ActionResult();
                result.setKey(light.getKey());
//                sr=controllerService.setControllerSwitch(Integer.parseInt(light.getTxcs()),fogArea.getJsdkg());
                result.setCzjg(sr.getResult().ordinal());
                results.add(result);
            }
            if(sr.getResult()==SendResult.Success)
            {
                //更新数据库
                fogAreaDAO.updateFogAreaLight(fogArea);

                //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
                setWarningCache(fogArea);
            }
        }
        else
        {
            //自动模式只需要更新数据库，等待下一次通知自动控制设备
            for(LinkDevice light:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Light))
            {
                ActionResult result=new ActionResult();
                result.setKey(light.getKey());
                result.setCzjg(SendResult.Success.ordinal());
                results.add(result);
            }
            //更新数据库
            fogAreaDAO.updateFogAreaLight(fogArea);

            //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
            setWarningCache(fogArea);
        }

        return results;
    }

    /**
     * 控制雾区限速屏
     * @param fogArea
     * @return
     * @throws IOException
     */
    public List<ActionResult> setLeds(String token,FogArea fogArea) throws IOException {

        List<ActionResult> results=new ArrayList<>();

        //手动模式需要下发
        if(fogArea.getXspgzms()==FogAreaWorkMode.Manual)
        {
            SendResult sendResult=SendResult.SendFailed;
            for(LinkDevice led:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Led))
            {
                ActionResult result=new ActionResult();
                result.setKey(led.getKey());
                int card=Integer.parseInt(led.getTxcs());
                int speed=fogArea.getXsz();
                int size=Integer.parseInt(led.getGgxh());
                sendResult=linkDeviceService.setLedSpeed(token,card,speed,size,led.getSbcj(),led.getIpdz(),led.getFwdk());
                result.setCzjg(sendResult.ordinal());
                results.add(result);
            }

            if(sendResult==SendResult.Success)
            {
                //更新数据库
                fogAreaDAO.updateFogAreaLed(fogArea);

                //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
                setLedCache(fogArea);
            }
        }
        else
        {
            for(LinkDevice led:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Led))
            {
                ActionResult result=new ActionResult();
                result.setKey(led.getKey());
                result.setCzjg(SendResult.Success.ordinal());
                results.add(result);
            }

            //更新数据库
            fogAreaDAO.updateFogAreaLed(fogArea);

            //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
            setLedCache(fogArea);
        }

        return results;
    }

    /**
     * 控制抓拍相机限速值
     * @param fogArea
     * @return
     * @throws IOException
     */
    public List<ActionResult> setCameras(String token,FogArea fogArea) throws IOException {

        List<ActionResult> results=new ArrayList<>();

        //手动模式需要下发
        if(fogArea.getXjgzms()==FogAreaWorkMode.Manual)
        {
            SendResult sendResult=SendResult.SendFailed;
            for(LinkDevice camera:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Camera))
            {
                ActionResult result=new ActionResult();
                result.setKey(camera.getKey());
                String cameraIp=camera.getIpdz();
                int smallLow=fogArea.getXcxszxx();
                int smallHigh=fogArea.getXcxszsx();
                int bigLow=fogArea.getDcxszxx();
                int bigHigh=fogArea.getDcxszsx();
                sendResult=linkDeviceService.setCameraSpeed(token,cameraIp,smallLow,smallHigh,bigLow,bigHigh);
                result.setCzjg(sendResult.ordinal());
                results.add(result);
            }

            if(sendResult==SendResult.Success)
            {
                //更新数据库
                fogAreaDAO.updateFogAreaCamera(fogArea);

                //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
                setCameraCache(fogArea);
            }
        }
        else
        {
            for(LinkDevice camera:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Camera))
            {
                ActionResult result=new ActionResult();
                result.setKey(camera.getKey());
                result.setCzjg(SendResult.Success.ordinal());
                results.add(result);
            }

            //更新数据库
            fogAreaDAO.updateFogAreaCamera(fogArea);
            //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
            setCameraCache(fogArea);
        }

        return results;
    }

    /**
     * 控制雾区号角
     * @param token
     * @param fogArea
     * @return
     * @throws IOException
     */
    public List<ActionResult> setHorns(String token, FogArea fogArea) throws IOException {

        List<ActionResult> results=new ArrayList<>();

        //手动模式需要下发
        if(fogArea.getHjgzms()==FogAreaWorkMode.Manual)
        {
            SendResult sendResult=SendResult.SendFailed;
            for(LinkDevice horn:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Horn))
            {
                ActionResult result=new ActionResult();
                result.setKey(horn.getKey());
                int id=Integer.parseInt(horn.getTxcs());
                int file=fogArea.getHjyy();
                int volume=fogArea.getHjyl();
                sendResult=linkDeviceService.setHornMusic(token,id,file,volume);
                result.setCzjg(sendResult.ordinal());
                results.add(result);
            }
            if(sendResult==SendResult.Success)
            {
                //更新数据库
                fogAreaDAO.updateFogAreaHorn(fogArea);

                //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
                setHornCache(fogArea);
            }
        }
        else
        {
            for(LinkDevice horn:linkDeviceDAO.getLinkDevices(fogArea.getWqbm(),DeviceType.Horn))
            {
                ActionResult result=new ActionResult();
                result.setKey(horn.getKey());
                result.setCzjg(SendResult.Success.ordinal());
                results.add(result);
            }
            //更新数据库
            fogAreaDAO.updateFogAreaHorn(fogArea);

            //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
            setHornCache(fogArea);
        }
        return results;
    }


    /**
     * 雾区切换至主控制器
     * @param fogArea 雾区
     * @param token token
     * @return 操作结果
     * @throws IOException
     */
    public SendResult setRelayMain(String token,FogArea fogArea) throws IOException {

        String joinId=UUID.randomUUID().toString();
        SocketResult result=controllerService.setRelayMain(fogArea,joinId);
        if(result.getResult()==SendResult.Success)
        {
            fogArea.setJdqgzms(RelayControlMode.Main);
            setRelayCache(fogArea);
            for(Controller controller:controllerService.getControllers(fogArea.getWqbm()))
            {
                ControllerConfigMap.remove(controller.getKzqbm());
            }
        }

        logService.insertSystemLog(token, SystemLogType.ControlRelay,String.format("雾区 %s 切换到主控制器",fogArea.getWqmc()),joinId);
        return result.getResult();
    }

    /**
     * 雾区切换至备用控制器
     * @param fogArea 雾区
     * @param token token
     * @return 操作结果
     * @throws IOException
     */
    public SendResult setRelayBak(String token,FogArea fogArea) throws IOException {

        String joinId=UUID.randomUUID().toString();
        SocketResult result=controllerService.setRelayBak(fogArea,joinId);
        if(result.getResult()==SendResult.Success)
        {
            fogArea.setJdqgzms(RelayControlMode.Bak);
            setRelayCache(fogArea);
            for(Controller controller:controllerService.getControllers(fogArea.getWqbm()))
            {
                ControllerConfigMap.remove(controller.getKzqbm());
            }
        }

        logService.insertSystemLog(token, SystemLogType.ControlRelay,String.format("雾区 %s 切换到备用控制器",fogArea.getWqmc()),joinId);
        return result.getResult();
    }

    /**
     * 雾区切换切换至星历控制器
     * @param fogArea 雾区
     * @param token token
     * @return 操作结果
     * @throws IOException
     */
    public SendResult setRelayOff(String token,FogArea fogArea) throws IOException {

        String joinId=UUID.randomUUID().toString();
        SocketResult result=controllerService.setRelayOff(fogArea,joinId);
        if(result.getResult()==SendResult.Success)
        {
            fogArea.setJdqgzms(RelayControlMode.Off);
            setRelayCache(fogArea);
            for(Controller controller:controllerService.getControllers(fogArea.getWqbm()))
            {
                ControllerConfigMap.remove(controller.getKzqbm());
            }
        }
        logService.insertSystemLog(token, SystemLogType.ControlRelay,String.format("雾区 %s 切换到星历继电器",fogArea.getWqmc()),joinId);
        return result.getResult();
    }

    /**
     * 更新继电器状态
     * @param fogArea 雾区
     */
    public void setRelayCache(FogArea fogArea)
    {
        FogArea fogAreaCache= FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setJdqgzms(fogArea.getJdqgzms());
            fogAreaCache.setJdqgzmssm(codeService.getCodeValue(CodeType.Jdqzt,fogAreaCache.getJdqgzms()));
        }
    }

    /**
     * 设置相机工作模式缓存
     * @param fogArea
     */
    private void setCameraCache(FogArea fogArea)
    {
        //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setXjgzms(fogArea.getXjgzms());
            fogAreaCache.setXjgzmssm(codeService.getCodeValue(CodeType.Gzms,fogAreaCache.getXjgzms()));
        }
    }

    /**
     * 设置号角工作模式缓存
     * @param fogArea
     */
    private void setHornCache(FogArea fogArea)
    {
        //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setHjgzms(fogArea.getHjgzms());
            fogAreaCache.setHjgzmssm(codeService.getCodeValue(CodeType.Gzms,fogAreaCache.getHjgzms()));
        }
    }

    /**
     * 设置限速屏工作模式缓存
     * @param fogArea
     */
    private void setLedCache(FogArea fogArea)
    {
        //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setXspgzms(fogArea.getXspgzms());
            fogAreaCache.setXspgzmssm(codeService.getCodeValue(CodeType.Gzms,fogAreaCache.getXspgzms()));
        }
    }

    /**
     * 设置报警灯工作模式缓存
     * @param fogArea
     */
    private void setWarningCache(FogArea fogArea)
    {
        //更新缓存工作模式，缓存需要这个字段判断是否在收到能见度通知时下发命令
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setJsdgzms(fogArea.getJsdgzms());
            fogAreaCache.setJsdgzmssm(codeService.getCodeValue(CodeType.Gzms,fogAreaCache.getJsdgzms()));
        }
    }

    /**
     * 更新天气缓存
     * @param fogArea 天气
     */
    private void setWeatherCache(FogArea fogArea)
    {
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setWd(fogArea.getWd());
            fogAreaCache.setSd(fogArea.getSd());
            fogAreaCache.setFx(fogArea.getFx());
            fogAreaCache.setFs(fogArea.getFs());
            fogAreaCache.setQy(fogArea.getQy());
            fogAreaCache.setYl(fogArea.getYl());
        }
    }

    /**
     * 更新路面缓存
     * @param fogArea 路面
     */
    private void setRoadCache(FogArea fogArea)
    {
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setDmwd(fogArea.getDmwd());
            fogAreaCache.setSmhd(fogArea.getSmhd());
            fogAreaCache.setBhd(fogArea.getBhd());
            fogAreaCache.setXhd(fogArea.getXhd());
            fogAreaCache.setShxs(fogArea.getShxs());
            fogAreaCache.setLmzt(codeService.getCodeValue(CodeType.Lmzt,fogArea.getLmztdm()));
        }
    }

    /**
     * 设置能见度缓存
     * @param fogArea
     */
    private void setVisibilityCache(FogArea fogArea)  {

        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            //检测仪状态
            fogAreaCache.setJcysbzt(fogArea.getJcysbzt());
            fogAreaCache.setJcysbztsm(codeService.getCodeValue(CodeType.Njdsbzt,DeviceStatus.Noraml));

            //能见度
            fogAreaCache.setNjd(fogArea.getNjd());
            fogAreaCache.setNjdyfz(fogArea.getNjdyfz());
            fogAreaCache.setNjdsfz(fogArea.getNjdsfz());

            fogAreaCache.setTqdm(fogArea.getTqdm());
            fogAreaCache.setTqdmsm(codeService.getCodeValue(CodeType.Tqdm,fogAreaCache.getTqdm()));

            //能见度等级
            VisibilityScale visibilityScale=visibilityScaleService.getVisibilityScale(fogAreaCache.getWqbm(),fogAreaCache.getNjd());
            fogAreaCache.setNjddj(visibilityScale.getNjddj());
            fogAreaCache.setNjddjms(visibilityScale.getNjddjms());
            fogAreaCache.setNjdsx(visibilityScale.getNjdsx());
            fogAreaCache.setNjdxx(visibilityScale.getNjdxx());

            //联动设备参数
            fogAreaCache.setJsdkg(visibilityScale.getJsdkg());
            fogAreaCache.setXsz(visibilityScale.getXsz());
            fogAreaCache.setHjyy(visibilityScale.getHjyy());
            fogAreaCache.setHjyl(visibilityScale.getHjyl());
            fogAreaCache.setXcxszxx(visibilityScale.getXcxszxx());
            fogAreaCache.setXcxszsx(visibilityScale.getXcxszsx());
            fogAreaCache.setDcxszxx(visibilityScale.getDcxszxx());
            fogAreaCache.setDcxszsx(visibilityScale.getDcxszsx());
        }
    }

    /**
     * 设置光感缓存
     * @param fogArea
     */
    private void setLightCache(FogArea fogArea)
    {
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        //更新缓存
        if(fogAreaCache!=null) {
            fogAreaCache.setKdfz(fogArea.getKdfz());
            fogAreaCache.setGdfz(fogArea.getGdfz());
            fogAreaCache.setQrcs(fogArea.getQrcs());
            fogAreaCache.setFwzq(fogArea.getFwzq());

            fogAreaCache.setTempQrcs(fogArea.getTempQrcs());
            fogAreaCache.setTempKdfz(fogArea.isTempKdfz());
            fogAreaCache.setControllers(fogArea.getControllers());
        }
    }

    /**
     * 设置雾区状态缓存
     * @param fogArea
     */
    private void setFogAreaStatusCache(FogArea fogArea)
    {
        //更新雾区设备相关字段的缓存
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        if(fogAreaCache!=null)
        {
            fogAreaCache.setWqmc(fogArea.getWqmc());

            //检测仪
            fogAreaCache.setJcybsm(fogArea.getJcybsm());
            fogAreaCache.setJcybh(fogArea.getJcybh());
            fogAreaCache.setJcydk(fogArea.getJcydk());

            //更新时间
            fogAreaCache.setGxsj(fogArea.getGxsj());

        }
    }

    /**
     * 设置工作模式缓存
     * @param fogArea
     */
    private void setWorkModeCache(FogArea fogArea)
    {
        FogArea fogAreaCache=FogAreaMap.get(fogArea.getWqbm());
        //更新缓存
        if(fogAreaCache!=null) {

            fogAreaCache.setGzms(fogArea.getGzms());

            fogAreaCache.setFact(fogArea.isFact());
            fogAreaCache.setFamc(fogArea.getFamc());
            fogAreaCache.setKssj(fogArea.getKssj());
            fogAreaCache.setCxsj(fogArea.getCxsj());

            //报警模式重新计算控制状态
            if (fogArea.getGzms() == FogAreaWorkMode.Warning) {
                int njd = 0;
                if (fogAreaCache != null) {
                    njd = fogAreaCache.getNjd();
                }
                if (njd == 0) {
                    fogAreaCache.setWdkz(ControllerWorkMode.Unknown);
                    fogAreaCache.setKzcl(ControlStrategy.Unknown);
                } else {
                    VisibilityScale visibilityScale = visibilityScaleService.getVisibilityScale(fogArea.getWqbm(), njd);
                    fogAreaCache.setKzcl(visibilityScale.getKzcl());
                    fogAreaCache.setSspl(visibilityScale.getSspl());
                    fogAreaCache.setZkb(visibilityScale.getZkb());
                    fogAreaCache.setWdlddj(visibilityScale.getWdlddj());

                    fogAreaCache.setWdkz(visibilityScale.getWdkz());
                    fogAreaCache.setWdld(visibilityScale.getWdld());
                    fogAreaCache.setLdsc(visibilityScale.getLdsc());
                    fogAreaCache.setMdsc(visibilityScale.getMdsc());
                    fogAreaCache.setHsjsdzsl(visibilityScale.getHsjsdzsl());
                    fogAreaCache.setHdys(visibilityScale.getHdys());
                    fogAreaCache.setMqys(visibilityScale.getMqys());
                }
            }
            else
            {
                fogAreaCache.setKzcl(fogArea.getKzcl());
                fogAreaCache.setSspl(fogArea.getSspl());
                fogAreaCache.setZkb(fogArea.getZkb());
                fogAreaCache.setWdlddj(fogArea.getWdlddj());

                fogAreaCache.setWdkz(fogArea.getWdkz());
                fogAreaCache.setWdld(fogArea.getWdld());
                fogAreaCache.setLdsc(fogArea.getLdsc());
                fogAreaCache.setMdsc(fogArea.getMdsc());
                fogAreaCache.setHdys(fogArea.getHdys());
                fogAreaCache.setMqys(fogArea.getMqys());
                fogAreaCache.setHsjsdzsl(fogArea.getHsjsdzsl());
            }

            fogAreaCache.setGzmssm(fogArea.getGzmssm());
            fogAreaCache.setWdkzsm(fogArea.getWdkzsm());
            fogAreaCache.setKzclsm(fogArea.getKzclsm());
            fogAreaCache.setSsplsm(fogArea.getSsplsm());
            fogAreaCache.setZkbsm(fogArea.getZkbsm());
            fogAreaCache.setWdlddjsm(fogArea.getWdlddjsm());
        }
    }

    public boolean checkWqbsm(int wqbm,String wqbsm)
    {
        FogArea fogArea=FogAreaMap.get(wqbm);
        if(fogArea==null)
        {
            return false;
        }
        if(fogArea.getWqbsm()==null)
        {
            return false;
        }
        return fogArea.getWqbsm().compareTo(wqbsm)==0;
    }
}
